﻿using CasignDesignGA.Casing;
using CasignDesignGA.Engine;
using CasignDesignGA.Engine.Population.FileReader;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace CasignDesignGA
{
    public partial class GAMain : Form
    {
        public GAMain()
        {
            InitializeComponent();
            
            AptitudeChart.Series.Add(CasingConstants.APTITUDE_CHART_AVERAGE_SERIE);
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_AVERAGE_SERIE].ChartType = SeriesChartType.Spline;
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_AVERAGE_SERIE].Color = Color.DarkOrange;
            //AptitudeChart.Series[CasingConstants.APTITUDE_CHART_AVERAGE_SERIE].Legend = CasingConstants.APTITUDE_CHART_AVERAGE_SERIE_STRING;

            AptitudeChart.Series.Add(CasingConstants.APTITUDE_CHART_BEST_SERIE);
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_BEST_SERIE].Color = Color.DarkSeaGreen;
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_BEST_SERIE].ChartType = SeriesChartType.Spline;
            //AptitudeChart.Series[CasingConstants.APTITUDE_CHART_BEST_SERIE].Legend = CasingConstants.APTITUDE_CHART_BEST_SERIE_STRING;


            AptitudeChart.Series.Add(CasingConstants.APTITUDE_CHART_WORST_SERIE);
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_WORST_SERIE].Color = Color.DarkRed;
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_WORST_SERIE].ChartType = SeriesChartType.Spline;
           // AptitudeChart.Series[CasingConstants.APTITUDE_CHART_WORST_SERIE].Legend = CasingConstants.APTITUDE_CHART_WORST_SERIE_STRING;

            PropertiesChart.Series.Add(CasingConstants.COLLAPSE_STRING);
            PropertiesChart.Series[CasingConstants.COLLAPSE_STRING].ChartType = SeriesChartType.Spline;
            PropertiesChart.Series.Add(CasingConstants.COLLAPSE_BEST_STRING);
            PropertiesChart.Series[CasingConstants.COLLAPSE_BEST_STRING].ChartType = SeriesChartType.Spline;

            PropertiesChart.Series.Add(CasingConstants.BURST_STRING);
            PropertiesChart.Series[CasingConstants.BURST_STRING].ChartType = SeriesChartType.Spline;
            PropertiesChart.Series[CasingConstants.BURST_STRING].Color = Color.Black;

            PropertiesChart.Series.Add(CasingConstants.BURST_BEST_STRING);
            PropertiesChart.Series[CasingConstants.BURST_BEST_STRING].ChartType = SeriesChartType.Spline;
            PropertiesChart.Series[CasingConstants.BURST_BEST_STRING].Color = Color.DarkOrchid;
            this.clearAptitudeChart();
        }

        private void clearAptitudeChart()
        {
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_AVERAGE_SERIE].Points.Clear();
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_BEST_SERIE].Points.Clear();
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_WORST_SERIE].Points.Clear();
        }

        private GAEngine myEngine;

        private void button2_Click(object sender, EventArgs e)
        {
            
            if (CrossingSiblingsTextBox.Text.Trim().Equals("") || WellDepthTextBox.Text.Trim().Equals("") || MutationFactor.Text.Trim().Equals("") || LifeTime.Text.Trim().Equals("") || TotalGenerationsTextBox.Text.Trim().Equals("") || InitialPopulationTextBox.Text.Trim().Equals(""))
            {
                MessageBox.Show("Please complete all the input text box");
            }
            else
            {
                double mutationFactor = Convert.ToDouble(MutationFactor.Text);
                long wellDepth = Convert.ToInt64(WellDepthTextBox.Text);
                Well.Well.Instance.Depth = wellDepth;
                long initialPopulation = Convert.ToInt64(InitialPopulationTextBox.Text);
                int lifeTime = Convert.ToInt32(LifeTime.Text);
                long totalGenerations = Convert.ToInt64(TotalGenerationsTextBox.Text);
                long crossingSiblings = Convert.ToInt64(CrossingSiblingsTextBox.Text);
                double designFactor = Convert.ToDouble(designFactorUpDown.Text);
                this.myEngine = new GAEngine(initialPopulation, totalGenerations, lifeTime, crossingSiblings, mutationFactor, designFactor);
                this.myEngine.reset();
                this.progressBar1.Maximum = (int)totalGenerations;
                this.progressBar1.Value = 0;
                this.clearAptitudeChart();
                this.myEngine.start();
                while (this.myEngine.CurrentGeneration < this.myEngine.MaxGenerations)
                {
                    this.myEngine.step();
                    this.updateGraph();
                    this.updateLabels();
                    this.progressBar1.Value++;
                    Thread.Sleep(500);
                }

                //showBestIndividual();

                this.updateCollapseGraph();
                this.updateBurstGraph();
            }
        }

        private void updateBurstGraph()
        {
            CasingProperty burstProperty = this.myEngine.CurrentPopulation.getBestIndividualBurst();

            drawProperty(burstProperty, CasingConstants.BURST_BEST_STRING);
        }

        private void updateCollapseGraph()
        {
           CasingProperty collapseProperty = this.myEngine.CurrentPopulation.getBestIndividualCollapse();
          
           drawProperty(collapseProperty, CasingConstants.COLLAPSE_BEST_STRING);
        }

        private void updateLabels()
        {
            this.BestLabel.Text = this.myEngine.CurrentPopulation.BestIndividualDescription();
            this.WorstLabel.Text = this.myEngine.CurrentPopulation.WorstIndividualDescription();
        }

        private void showBestIndividual()
        {
            string bestIndividualDescription = this.myEngine.CurrentPopulation.BestIndividualDescription();
            
            MessageBox.Show(bestIndividualDescription);
            

        }

        private void showWorstIndividual()
        {
            
            string worstIndividualDescription = this.myEngine.CurrentPopulation.WorstIndividualDescription();
            MessageBox.Show(worstIndividualDescription);


        }

        public void updateGraph()
        {
            

            DataPoint aAverageDataPoint = new DataPoint(this.myEngine.CurrentGeneration, this.myEngine.CurrentPopulation.AverageAptitude);
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_AVERAGE_SERIE].Points.Add(aAverageDataPoint);
            
            DataPoint aBestDataPoint = new DataPoint(this.myEngine.CurrentGeneration, this.myEngine.CurrentPopulation.BestAptitude);
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_BEST_SERIE].Points.Add(aBestDataPoint);

            DataPoint aWorstDataPoint = new DataPoint(this.myEngine.CurrentGeneration, this.myEngine.CurrentPopulation.WorstAptitude);
            AptitudeChart.Series[CasingConstants.APTITUDE_CHART_WORST_SERIE].Points.Add(aWorstDataPoint);

            AptitudeChart.Update();
            
        }
        
        public void GAMain_Load(object sender, System.EventArgs e)
        {
            
            CSVFileReader fileReader = new CSVFileReader();

            CasingCatalog.Instance.Catalog = fileReader.readCasingCatalogFile(CasingConstants.CATALOG_FILE);

            fileReader.readCasingPropertiesFile(CasingConstants.BURST_FILE, CasingConstants.BURST_PROPERTY);

            fileReader.readCasingPropertiesFile(CasingConstants.COLLAPSE_FILE,CasingConstants.COLLAPSE_PROPERTY);
            PropertiesChart.ChartAreas[0].AxisX.Title = CasingConstants.PRESSURE;
            PropertiesChart.ChartAreas[0].AxisY.Title = CasingConstants.DEPTH;
            PropertiesChart.ChartAreas[0].AxisY.IsReversed = true;
            PropertiesChart.ChartAreas[0].AxisY.ArrowStyle = AxisArrowStyle.SharpTriangle;
            PropertiesChart.ChartAreas[0].AxisX.ArrowStyle = AxisArrowStyle.SharpTriangle;           
            PropertiesChart.ChartAreas[0].AxisX.Minimum = 0;
            drawBurstProperty();
            drawCollapseProperty();


        }

        private void drawCollapseProperty()
        {
            
            CasingProperty collapseProperty = CasingProperties.Instance.getProperty(CasingConstants.COLLAPSE_PROPERTY);
            drawProperty(collapseProperty,CasingConstants.COLLAPSE_STRING);
        }

        private void drawBurstProperty()
        {
            
            CasingProperty burstProperty = CasingProperties.Instance.getProperty(CasingConstants.BURST_PROPERTY);
            drawProperty(burstProperty, CasingConstants.BURST_STRING);
              
            
            
        }

        private void drawProperty(CasingProperty aProperty, string seriesString)
        {
            PropertiesChart.Series[seriesString].Points.Clear();
            
            if (aProperty != null)
            {
                
                foreach (double key in aProperty.getKeys())
                {
                    double valueDouble = aProperty.getKeyValue(key);

                    DataPoint aDataPoint = new DataPoint(valueDouble, key);
                    PropertiesChart.Series[seriesString].Points.Add(aDataPoint);
                }

            }

            
        }

        private void WellDepthTextBox_TextChanged(object sender, EventArgs e)
        {
            if (System.Text.RegularExpressions.Regex.IsMatch(WellDepthTextBox.Text, "[^0-9]"))
            {
                MessageBox.Show("Please enter only numbers in well depth text box.");
                WellDepthTextBox.Text="";
            }
        }
       
      

        private void InitialPopulationTextBox_TextChanged(object sender, EventArgs e)
        {
            if (System.Text.RegularExpressions.Regex.IsMatch(InitialPopulationTextBox.Text, "[^0-9]"))
            {
                MessageBox.Show("Please enter only numbers in initial population text box.");
                InitialPopulationTextBox.Text = "";
            }
        }

        private void TotalGenerationsTextBox_TextChanged(object sender, EventArgs e)
        {
            if (System.Text.RegularExpressions.Regex.IsMatch(TotalGenerationsTextBox.Text, "[^0-9]"))
            {
                MessageBox.Show("Please enter only numbers in total generations text box.");
                TotalGenerationsTextBox.Text = "";
            }
        }


        private void CrossingSiblingsTextBox_TextChanged(object sender, EventArgs e)
        {
            if (System.Text.RegularExpressions.Regex.IsMatch(CrossingSiblingsTextBox.Text, "[^0-9]"))
            {
                MessageBox.Show("Please enter only numbers in crossing siblings text box.");
                TotalGenerationsTextBox.Text = "";
            }
        }

      

        

        

       

    }
}
